/*================================================================================================*/
/**
*   @file    sys_init.c
*   @version 1.0.4
*
*   @brief   AUTOSAR Sample_app - MCAL auxiliary APIs used for MCAL testing
*   @details MCAL auxiliary APIs used for MCAL testing
*            This file contains sample code only. It is not part of the production code deliverables
*   @addtogroup BUILD_ENV
*   @{
*/
/*==================================================================================================
*   Project              : AUTOSAR 4.0 MCAL
*   Platform             : ARM
*
*   Autosar Version      : 4.0.3
*   Autosar Revision     : ASR_REL_4_0_REV_0003
*   Autosar Conf.Variant :
*   SW Version           : 1.0.4
*   Build Version        : S32K14X_MCAL_1_0_4_RTM_ASR_REL_4_0_REV_0003_20190307
*
*   (c) Copyright 2019 NXP
*   All Rights Reserved.
==================================================================================================*/
/*==================================================================================================
==================================================================================================*/

#ifdef __cplusplus
extern "C" {
#endif

    
/*==================================================================================================
*                                         INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "sys_init.h"
#include "Mcal.h"
#include "StdRegMacros.h"
#ifdef S32K142
    #include "s32k142.h"
#endif
#ifdef S32K144
    #include "s32k144.h"
#endif
#ifdef S32K148
    #include "s32k148.h"
#endif

#include "nvic.h"
/*==================================================================================================
*                                        LOCAL MACROS
==================================================================================================*/

/*==================================================================================================
*                                      FILE VERSION CHECKS
==================================================================================================*/

/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                       GLOBAL CONSTANTS
==================================================================================================*/
uint32_t  DummyVar=0x56788765;
/*==================================================================================================
*                                       GLOBAL VARIABLES
==================================================================================================*/

/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/
#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
    extern uint32 startup_getControlRegisterValue(void);
    extern uint32 startup_getAipsRegisterValue(void);
#endif
void startup_go_to_user_mode(void);

/*================================================================================================*/
/**
* @brief    startup_go_to_user_mode
* @details  Function called from startup.s to switch to user mode if MCAL_ENABLE_USER_MODE_SUPPORT
*           is defined
*/
/*================================================================================================*/
void startup_go_to_user_mode(void)
{
#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
    ASM_KEYWORD("svc 0x1");
#endif
}

/*================================================================================================*/
/**
* @brief Sys_GoToSypervisor
* @details function used to enter to supervisor mode.
            check if it's needed to switch to supervisor mode and make the switch.
            Return 1 if switch was done
*/
/*================================================================================================*/

#ifdef MCAL_ENABLE_USER_MODE_SUPPORT

/* check if it's needed to switch to supervisor mode and make the switch.
Return 1 if switch was done */
uint8 Sys_GoToSupervisor(void)
{
    VAR(uint32, MCU_VAR) u32ControlRegValue;
    VAR(uint32, MCU_VAR) u32AipsRegValue;
    VAR(uint8, MCU_VAR)  u8SwithcToSupervisor;
    /* if it's 0 then Thread mode is already in supervisor mode */
    u32ControlRegValue = startup_getControlRegisterValue();
    /* if it's 0 the core is in Thread mode, otherwise in Handler mode */
    u32AipsRegValue = startup_getAipsRegisterValue();
    /* if core is already in supervisor mode for Thread mode, or running form Handler mode, there is no need to make the switch */
    if((0UL == (u32ControlRegValue & 1)) || (0 < (u32AipsRegValue & 0xFF)))
    {
        u8SwithcToSupervisor = 0U;
    }
    else
    {
        u8SwithcToSupervisor = 1U;
        Mcal_goToSupervisor();
    }
    return u8SwithcToSupervisor;
}

/*================================================================================================*/
/**
* @brief Sys_ToUser_Return
* @details function used to switch back to user mode for Thread mode, return a uint32 value passed as parameter
*/
/*================================================================================================*/
uint32 Sys_GoToUser_Return(uint8 u8SwithcToSupervisor, uint32 u32returnValue)
{
      if(1UL == u8SwithcToSupervisor)
      {
        Mcal_goToUser();
      }
      return u32returnValue;
}
/*make the switch back to user mode for Thread mode, return 0. */
 uint32 Sys_GoToUser(void)
{
        Mcal_goToUser();
        return 0UL;
}
#endif
/*=================================================================================================*/

/* To Initialize both caches, make these two function calls
 *  m4_cache_init(CODE_CACHE);
 *  m4_cache_init(SYS_CACHE);
 */

uint8_t m4_cache_init(uint8_t cache)
{

  if (cache == CODE_CACHE)
  {
      /* Code Cache Init */

      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM->PCCCR = 0x05000000;

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PCCCR |= LMEM_PCCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) == LMEM_PCCCR_GO_MASK);

      /* enable cache */
      LMEM->PCCCR |= LMEM_PCCCR_ENCACHE(1);

  }else if (cache == SYS_CACHE)
  {
#if 0
      /* System Cache Init */

      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM->PSCCR = 0x05000000;

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PSCCR |= LMEM_PSCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) == LMEM_PSCCR_GO_MASK);

      /* enable write buffer */
      LMEM->PSCCR |= LMEM_PSCCR_ENWRBUF(1);

      /* enable cache */
      LMEM->PSCCR |= LMEM_PSCCR_ENCACHE(1);
#endif
  } else
  {
     return CACHE_INVALID_PARAM;
  }

  return CACHE_OK;
}


uint8_t m4_cache_disable(uint8_t cache)
{

  if (cache == CODE_CACHE)
  {
       /* Disable code cache */
       LMEM->PCCCR = 0;

  }else if (cache == SYS_CACHE)
  {
       /* Disable system cache */
       /*LMEM->PSCCR = 0; */

  } else
  {
     return CACHE_INVALID_PARAM;
  }

  return CACHE_OK;
}


uint8_t m4_cache_invalidate(uint8_t cache)
{

  if (cache == CODE_CACHE)
  {
      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM->PCCCR = 0x05000000; /* set INVW0 and INVW1 */

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PCCCR |= LMEM_PCCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) == LMEM_PCCCR_GO_MASK);

  }else if (cache == SYS_CACHE)
  {
#if 0
      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM.PSCCR.R = 0x05000000; /* set INVW0 and INVW1 */

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PSCCR |= LMEM_PSCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) == LMEM_PSCCR_GO_MASK);
#endif
  } else
  {
     return CACHE_INVALID_PARAM;
  }

  return CACHE_OK;

}

uint8_t m4_cache_flush(uint8_t cache)
{

  if (cache == CODE_CACHE)
  {
      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM->PCCCR = 0x0A000000; /* set INVW0 and INVW1 */

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PCCCR |= LMEM_PCCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PCCCR & LMEM_PCCCR_GO_MASK) == LMEM_PCCCR_GO_MASK);

  }else if (cache == SYS_CACHE)
  {
#if 0     
      /* Cache Set Command: set command bits in CCR */
      /* set invalidate way 1 and invalidate way 0 bits */
      LMEM->PSCCR = 0x0A000000; /* set INVW0 and INVW1 */

      /* set ccr[go] bit to initiate command to invalidate cache */
      LMEM->PSCCR |= LMEM_PSCCR_GO(1);

      /* wait until the ccr[go] bit clears to indicate command complete */
      while((LMEM->PSCCR & LMEM_PSCCR_GO_MASK) == LMEM_PSCCR_GO_MASK);
#endif      
  } else
  {
     return CACHE_INVALID_PARAM;
  }

  return CACHE_OK;
}

uint8_t m4_cache_invalidate_buffer(uint32_t start_addr, long size)
{
  /* 32B line size => number of loops = size to invalidate divided by line size in bits plus 1 */
  uint32_t loops = size/32;
  uint32_t addr = start_addr;
  uint32_t i;
  
  for (i=0; i<loops; i++,addr+=32){
    /* LACC 27        - Read:             0x0  */
    /* LADSEL 26      - Physical Address: 0x1  */
    /* LCMD 25-24     - Invalidate:       0x01 */
    /* TDSEL 16       - Data:             0x0  */
    /* WSEL 14        - Way 0:            0x0  */
    LMEM->PCCLCR = 0x05000000;
    
    /* set physical address as start address with 2 LSB dropped */
    LMEM->PCCSAR = addr&0xFFFFFFFC;
    
    /* set csar[lgo] to initiate command indicated by bits 27-24 in clcr */
    LMEM->PCCSAR |= LMEM_PCCSAR_LGO(1);
    
    /* wait until the csar[lgo] bit clears to indicate command complete */
    while((LMEM->PCCSAR & LMEM_PCCSAR_LGO_MASK) == LMEM_PCCSAR_LGO_MASK);
  }
  
  return CACHE_OK;
}

uint8_t m4_cache_flush_buffer(uint32_t start_addr, long size)
{
  /* 32B line size => number of loops = size to invalidate divided by line size in bits plus 1 */
  uint32_t loops = size/32;
  uint32_t addr = start_addr;
  uint32_t i;
  
  for (i=0; i<loops; i++,addr+=32){
    /* LACC 27        - Read:             0x0  */
    /* LADSEL 26      - Physical Address: 0x1  */
    /* LCMD 25-24     - Push:             0x10 */
    /* TDSEL 16       - Data:             0x0  */
    /* WSEL 14        - Way 0:            0x0  */
    LMEM->PCCLCR = 0x06000000;
    
    /* set physical address as start address with 2 LSB dropped */
    LMEM->PCCSAR = addr&0xFFFFFFFC;
    
    /* set csar[lgo] to initiate command indicated by bits 27-24 in clcr */ 
    LMEM->PCCSAR |= LMEM_PCCSAR_LGO(1);
    
    /* wait until the csar[lgo] bit clears to indicate command complete */
    while((LMEM->PCCSAR & LMEM_PCCSAR_LGO_MASK) == LMEM_PCCSAR_LGO_MASK);
  }
  
  return CACHE_OK;
}

/** 
* @brief sys_init
* @details function used to enable all interrupts
*/
void sys_enableAllInterrupts(void)
{
    ResumeAllInterrupts();
}
/** 
* @brief sys_init
* @details function used to disable all interrupts
*/
void sys_disableAllInterrupts(void)
{
    SuspendAllInterrupts();
}
/** 
* @brief sys_init
* @details function used to disable the interrupt number id
*/
void sys_disableIsrSource(uint8 id)
{
    NVIC_DisableIRQ(id);
}
/** 
* @brief sys_init
* @details function used to enable the interrupt number id and set up the priority
*/
void sys_enableIsrSource(uint8 id, uint8 prio)
{
    NVIC_SetPriority(id, prio);
    NVIC_EnableIRQ(id);
}
/** 
* @brief sys_init
* @details function used to register the interrupt handler in the interrupt vector
*/
void  sys_registerIsrHandler(uint8_t irq_id, uint32 isr_handler)
{

#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
	Mcal_goToSupervisor();
#endif
   REG_WRITE32(S32_SCB->VTOR + ((16 + irq_id) << 2), isr_handler);
#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
	Mcal_goToUser();
#endif   

}
    
#ifdef __ICCARM__ 
    #pragma default_function_attributes = @ ".systeminit"
#else
    __attribute__ ((section (".systeminit")))
#endif 

#ifdef __ICCARM__ 
/* Initialize RAM variables and RAM functions */
void Scatter_Loading(void)
{

    volatile char * from; 
    volatile char * to;     
    volatile uint32 length;   

#pragma language=extended 
    /* Relocate the INT Vect table */
    #pragma section = "AppIntVec_Init"
    #pragma section = "AppIntVec"
    from = (char *)__segment_begin("AppIntVec_Init");
    to = (char *)__segment_begin("AppIntVec");
    length = __segment_size("AppIntVec");

     while(length--)
    {
        *to++ = *from++;

    }
    
    /* Relocate the  RAM code */
    #pragma section = "AppRAMCode"
    #pragma section = "AppRAMCode_Init"
    from = (char *)__segment_begin("AppRAMCode_Init");
    to = (char *)__segment_begin("AppRAMCode");
    length = __segment_size("AppRAMCode");
    while(length--)
    {
        *to++ = *from++;
    }
        
    /* Init DATA section */
    #pragma section = "AppData"
    #pragma section = "AppData_Init"
    from = (char *)__segment_begin("AppData_Init");
    to = (char *)__segment_begin("AppData");
    length = __segment_size("AppData");
    while(length--)
    {
        *to++ = *from++;
    }
    
    /* Init DATA NO_CACHE section */
    #pragma section = "AppData_NO_CACHE"
    #pragma section = "AppData_NO_CACHE_Init"
    from = (char *)__segment_begin("AppData_NO_CACHE_Init");
    to = (char *)__segment_begin("AppData_NO_CACHE");
    length = __segment_size("AppData_NO_CACHE");
    while(length--)
    {
        *to++ = *from++;
    }
    #pragma language=default
}
#endif /* #ifdef __ICCARM__ */


/*
 * system initialization : system clock, interrupt router ...
 */
void SystemInit(void)
{

    NVIC_SetPriorityGrouping(0); /* 0 means 7 bits for prio, 1 for sub-prio */

    S32_SCB->CCR    |=  1;       /**< processor can enter Thread mode from any level under the 
                                   control of an EXC_RETURN value, PendSV priority set to 0*/
    REG_BIT_CLEAR32(&(S32_SCB->SHPR3), S32_SCB_SHPR3_PRI_14_MASK); 
    
    /* enable the AIPS */
    AIPS->MPRA = 0x77777777;      
    AIPS->PACR[0]  = 0x0; 
    AIPS->PACR[1]  = 0x0; 
    AIPS->PACR[2]  = 0x0;  
    AIPS->PACR[3]  = 0x0; 
    AIPS->OPACR[0] = 0x0; 
    AIPS->OPACR[1] = 0x0; 
    AIPS->OPACR[2] = 0x0; 
    AIPS->OPACR[3] = 0x0; 
    AIPS->OPACR[4] = 0x0; 
    AIPS->OPACR[5] = 0x0; 
    AIPS->OPACR[6] = 0x0; 
    AIPS->OPACR[7] = 0x0; 
    AIPS->OPACR[8] = 0x0; 
    AIPS->OPACR[9] = 0x0; 
    AIPS->OPACR[10] = 0x0;
    AIPS->OPACR[11] = 0x0;
   
  
#if 0
    /* Enable speculative prefetching for program flash (flash bank 0) */
	MSCM->OCMDR[0] |= MSCM_OCMDR_OCMC1(2);
	/* Enable speculative prefetching for data flash (flash bank 1) */
	MSCM->OCMDR[1] |= MSCM_OCMDR_OCMC1(2);
#endif
	/* Configure slave ports to fixed-priority arbitration (default after reset) */
	MCM->CPCR &= ~MCM_CPCR_CBRR_MASK;

	/* Configure the SRAM_L and SRAM_U arbitration scheme to fixed priority (processor has highest, backdoor has lowest) */
	MCM->CPCR = MCM_CPCR_SRAMLAP(2) | MCM_CPCR_SRAMUAP(2); 
 
    
#ifdef D_CACHE_ENABLE    
    /*init Data caches*/
    m4_cache_init(SYS_CACHE);
#endif

#ifdef I_CACHE_ENABLE  
    /*init Code caches*/
    m4_cache_init(CODE_CACHE);
#endif

    
}


/**
* @brief sys_init
* @details function used to initiatialize clocks, system clock is system Pll 120 MHz
* @return E_NOT_OK/E_OK
*/
/*================================================================================================*/
Std_ReturnType sys_init(void)
{
#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
	Mcal_goToSupervisor();
#endif

	/* trimmed LPO to have 128Khz*/
	PMC->LPOTRIM=0;
    /* System clock initialization */
    
    
    /* FIRC Configuration */
    SCG->FIRCDIV=0x000201u;   /* SCG_FIRCDIV: FIRCDIV2=2, FIRCDIV1=1 */
    SCG->FIRCCFG=0x00;        /* SCG_FIRCCFG: RANGE=0 */
    while(SCG->FIRCCSR & 0x00800000u);
    SCG->FIRCCSR=0x00000001u;   /* SCG_FIRCCSR: FIRCEN=1 */
    while(!(SCG->FIRCCSR & 0x01000000));
    
    /* SIRC Configuration */
    SCG->SIRCDIV=0x00201u;   /* SCG_SIRCDIV: SIRCDIV2=2, SIRCDIV1=1 */
    SCG->SIRCCFG=0x01;       /* SCG_SIRCCFG: RANGE=1 */
    while(SCG->SIRCCSR & 0x00800000u);
    SCG->SIRCCSR=0x1u;       /* SCG_SIRCCSR: SIRCEN=1 */
    while(!(SCG->SIRCCSR & 0x01000000u));
    
    /* SOSC Configuration */ 
    SCG->SOSCDIV = 0x00010101u;  /* SCG_SOSCDIV: SOSCDIV3=1, SOSCDIV2=1, SOSCDIV1=1 */  
    SCG->SOSCCFG = 0x00000024u;  /* SCG_SOSCCFG: RANGE=2, EREFS=1 */
    while(SCG->SOSCCSR & 0x00800000u);
    SCG->SOSCCSR= 0x5u;           /* SCG_SOSCCSR: SOSCLPEN=1, SOSCEN=1 */
    while(!(SCG->SOSCCSR & 0x01000000u));
        
    SCG->RCCR=0x03010001U;  
    while(SCG->SPLLCSR & 0x00800000u);
    SCG->SPLLCSR=0x0U;  

    /* SPLL Configuration 80MHz =  PLLCLK= (IN_CLK * MUL)/(2*(PREDIV+1)) */ 
    SCG->SPLLDIV = 0x00201u;     
    SCG->SPLLCFG = 0x40000u;     /* SCG_SPLLCFG: MULT=5, PREDIV=0, SOURCE=0 */
    SCG->SPLLCSR=0x01;           /* SCG_SPLLCSR: SPLLEN=1 */
    while(!(SCG->SPLLCSR & 0x01000000u));
    
    SCG->RCCR=0x06010001U;  /* RUN Mode Configuration - system clock is 48Mhz*/
    SCG->VCCR=0x02010003U;  /* VLPR Mode Configuration */
    SCG->HCCR=0x06000013U;  /* HSPR Mode Configuration */

#if 0
    SMC->PMPROT = 0x80; /* Allow high speed run */
    SMC->PMCTRL = 0x60; /* Switch to high speed run */
#endif

/* disable peripherals clock */
    /* REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTFC_INDEX]), PCC_PCCn_CGC_MASK);    */   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_DMAMUX_INDEX]), PCC_PCCn_CGC_MASK);    
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FlexCAN0_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FlexCAN1_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM3_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_ADC1_INDEX]), PCC_PCCn_CGC_MASK);
#if defined(S32K144)||defined(S32K148)
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FlexCAN2_INDEX]), PCC_PCCn_CGC_MASK); 
#endif	
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPSPI0_INDEX]), PCC_PCCn_CGC_MASK);     
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPSPI1_INDEX]), PCC_PCCn_CGC_MASK);  
#if defined(S32K144)|| defined(S32K148)	
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPSPI2_INDEX]), PCC_PCCn_CGC_MASK); 
#endif	
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PDB1_INDEX]), PCC_PCCn_CGC_MASK);       
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_CRC_INDEX]), PCC_PCCn_CGC_MASK);        
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PDB0_INDEX]), PCC_PCCn_CGC_MASK);       
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPIT_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM0_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM1_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM2_INDEX]), PCC_PCCn_CGC_MASK);   
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_ADC0_INDEX]), PCC_PCCn_CGC_MASK); 
	REG_BIT_CLEAR32(&(PCC->PCCn[PCC_RTC_INDEX]), PCC_PCCn_CGC_MASK);
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPTMR0_INDEX]), PCC_PCCn_CGC_MASK);         
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PORTA_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PORTB_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PORTC_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PORTD_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_PORTE_INDEX]), PCC_PCCn_CGC_MASK);
#if defined(S32K148)
	REG_BIT_CLEAR32(&(PCC->PCCn[PCC_SAI0_INDEX]), PCC_PCCn_CGC_MASK);      
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_SAI1_INDEX]), PCC_PCCn_CGC_MASK);
#endif	
#if defined(S32K144)||defined(S32K148)
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FLEXIO_INDEX]), PCC_PCCn_CGC_MASK); 
#endif
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_EWM_INDEX]), PCC_PCCn_CGC_MASK);        
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPI2C0_INDEX]), PCC_PCCn_CGC_MASK); 
#if defined(S32K148)
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPI2C1_INDEX]), PCC_PCCn_CGC_MASK);
#endif	
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPUART0_INDEX]), PCC_PCCn_CGC_MASK);    
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPUART1_INDEX]), PCC_PCCn_CGC_MASK); 
#if defined(S32K144)||defined(S32K148)
	REG_BIT_CLEAR32(&(PCC->PCCn[PCC_LPUART2_INDEX]), PCC_PCCn_CGC_MASK);
#endif
#if defined(S32K148)
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM4_INDEX]), PCC_PCCn_CGC_MASK); 
	REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM5_INDEX]), PCC_PCCn_CGC_MASK);
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM6_INDEX]), PCC_PCCn_CGC_MASK);
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_FTM7_INDEX]), PCC_PCCn_CGC_MASK);
#endif
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_CMP0_INDEX]), PCC_PCCn_CGC_MASK); 
#if defined(S32K148)
    REG_BIT_CLEAR32(&(PCC->PCCn[PCC_QSPI_INDEX]), PCC_PCCn_CGC_MASK); 
	REG_BIT_CLEAR32(&(PCC->PCCn[PCC_ENET_INDEX]), PCC_PCCn_CGC_MASK);
#endif	

    /* enable and set peripherals clock */
	/* PCC->PCCn[PCC_FTFC_INDEX]= 0x43000000;   */   
    PCC->PCCn[PCC_DMAMUX_INDEX]= 0x43000000;  
    PCC->PCCn[PCC_FlexCAN0_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_FlexCAN1_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_FTM3_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_ADC1_INDEX]= 0x43000000;
#if defined(S32K144)||defined(S32K148)
    PCC->PCCn[PCC_FlexCAN2_INDEX]= 0x43000000; 
#endif	
    PCC->PCCn[PCC_LPSPI0_INDEX]= 0x43000000;     
    PCC->PCCn[PCC_LPSPI1_INDEX]= 0x43000000;  
#if defined(S32K144)|| defined(S32K148)	
    PCC->PCCn[PCC_LPSPI2_INDEX]= 0x43000000; 
#endif	
    PCC->PCCn[PCC_PDB1_INDEX]= 0x43000000;       
    PCC->PCCn[PCC_CRC_INDEX]= 0x43000000;        
    PCC->PCCn[PCC_PDB0_INDEX]= 0x43000000;       
    PCC->PCCn[PCC_LPIT_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_FTM0_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_FTM1_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_FTM2_INDEX]= 0x43000000;   
    PCC->PCCn[PCC_ADC0_INDEX]= 0x43000000; 
	PCC->PCCn[PCC_RTC_INDEX]= 0x43000000;
    PCC->PCCn[PCC_LPTMR0_INDEX]= 0x43000000;         
    PCC->PCCn[PCC_PORTA_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_PORTB_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_PORTC_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_PORTD_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_PORTE_INDEX]= 0x43000000;
#if defined(S32K148)
	PCC->PCCn[PCC_SAI0_INDEX]= 0x43000000;      
    PCC->PCCn[PCC_SAI1_INDEX]= 0x43000000;
#endif	
#if defined(S32K144)||defined(S32K148)
    PCC->PCCn[PCC_FLEXIO_INDEX]= 0x43000000; 
#endif
	PCC->PCCn[PCC_EWM_INDEX]= 0x43000000;        
    PCC->PCCn[PCC_LPI2C0_INDEX]= 0x43000000; 
#if defined(S32K148)
    PCC->PCCn[PCC_LPI2C1_INDEX]= 0x43000000;
#endif	
    PCC->PCCn[PCC_LPUART0_INDEX]= 0x43000000;    
    PCC->PCCn[PCC_LPUART1_INDEX]= 0x43000000; 
#if defined(S32K144)||defined(S32K148)
	PCC->PCCn[PCC_LPUART2_INDEX]= 0x43000000;
#endif
#if defined(S32K148)
    PCC->PCCn[PCC_FTM4_INDEX]= 0x43000000; 
	PCC->PCCn[PCC_FTM5_INDEX]= 0x43000000;
    PCC->PCCn[PCC_FTM6_INDEX]= 0x43000000;
    PCC->PCCn[PCC_FTM7_INDEX]= 0x43000000;
#endif
    PCC->PCCn[PCC_CMP0_INDEX]= 0x43000000; 
#if defined(S32K148)
    PCC->PCCn[PCC_QSPI_INDEX]= 0x43000000; 
	PCC->PCCn[PCC_ENET_INDEX]= 0x43000000;
#endif	


    /* Set PTE4 as BUSOUT (TP5 on daughter card) */
    PORTE->PCR[4]=0x200;
     
    /* Disable MPU */
    MPU->CESR = 0x00815200; 
     
#ifdef MCAL_ENABLE_USER_MODE_SUPPORT
	Mcal_goToUser();
#endif
    return E_OK;   
    
}

/*================================================================================================*/
/**
* @brief sys_halt
* @details function used to enter halt mode
*/
/*================================================================================================*/
void sys_halt(void)
{
 
    EXECUTE_WAIT();
}
/*================================================================================================*/
/**
* @brief sys_stop
* @details function used to enter stop mode
*/
/*================================================================================================*/
void sys_stop(void)
{
    EXECUTE_WAIT();
}

#ifdef __ICCARM__ 
    #pragma default_function_attributes =
#endif

#ifdef __cplusplus
}
#endif
